package com.jrowny.proxy
{
	import com.jrowny.controls.SpriteElement;
	import com.jrowny.enum.Notes;
	
	import mx.collections.ArrayCollection;
	import mx.events.CollectionEvent;
	import mx.utils.object_proxy;
	
	import org.puremvc.as3.patterns.proxy.Proxy;
	
	public class ElementProxy extends Proxy
	{
		
		public static const NAME:String = "ElementProxy";
		
		private var _curElm:SpriteElement;
		private var _elmMap:Object; //the element map
		
		public function ElementProxy()
		{
			super(NAME, new ArrayCollection());
			_elmMap = new Object();
			elements.addEventListener(CollectionEvent.COLLECTION_CHANGE,onChange);
		}
		
		//returns true if the size of the non-pseudo class is the same, if it doesn't exist or it is not, then don't return true.
		public function nonPseudoSizeMatch(selector:String,width:Number,height:Number):Boolean{
			if(_elmMap[selector] &&  (_elmMap[selector] as Array).length){
				for each(var elm:SpriteElement in _elmMap[selector]){
					if(elm.pseudo.length == 0 && elm.width == width && elm.height == height) return true; //we found a non psuedo class and the widths/heights match
				}
			}
			return false;
		}
		
		//We need to rebuid the map if things have changed
		public function changeElement(newSelector:String,oldSelector:String):void{
			if(newSelector!=oldSelector) rebuildMap(oldSelector);	//if the selector is different, rebuild both
			rebuildMap(newSelector);
			this.sendNotification(Notes.ELEMENTS_CHANGED,elements);
		}
		private function rebuildMap(selector:String):void{
			delete(_elmMap[selector]); //delete it, start over
			_elmMap[selector] = new Array();
			for each(var elm:SpriteElement in elements){
				if(elm.baseSelector == selector){	//is this element part of this map?
					(_elmMap[elm.baseSelector] as Array).push(elm);
				}
			}
			if(!(_elmMap[selector] as Array).length) delete(_elmMap[selector]); //cleanup
		}
		public function addElement(elm:SpriteElement):void{
			elements.addItem(elm);			
			/*
				the map stores elements by their base selector, that way we don't 
				create duplicate elements for psuedo class elements
			*/			
			if(!_elmMap[elm.baseSelector]){//doesn't exist
				_elmMap[elm.baseSelector] = new Array();		//create array of elements
				(_elmMap[elm.baseSelector] as Array).push(elm);	//add this guy
			}else{
				(_elmMap[elm.baseSelector] as Array).push(elm);
			}
		}
		public function removeElement(elm:SpriteElement):void{
			elements.removeItemAt(elements.getItemIndex(elm));
			
			//try to clean up the element map
			try{
				var map:Array = _elmMap[elm.baseSelector] as Array;
				if(map.length == 1){
					delete(_elmMap[elm.baseSelector]);	//remove this from the map
				}else{
					map.splice(map.indexOf(elm),1);
				}
			}catch(e:*){
				trace(e);
			}
			this.sendNotification(Notes.ELEMENTS_CHANGED,elements);
		}
		
		//handlers
		private function onChange(event:CollectionEvent):void{
			this.sendNotification(Notes.ELEMENTS_CHANGED,elements);
		}
		
		
		//accessors
		public function get elmMap():Object{
			return _elmMap;
		}
		public function set elmMap(value:Object):void{
			_elmMap = value;
		}
		
		public function get curElm():SpriteElement{
			return _curElm;
		}
		public function set curElm(value:SpriteElement):void{
			_curElm = value;
			this.sendNotification(Notes.ELEMENT_SELECTED,_curElm);
		}
				
		public function get elements():ArrayCollection{
			return data as ArrayCollection;
		}
		public function set elements(value:ArrayCollection):void{
			data = value as ArrayCollection;
		}
		
	}
}